/************************************************************************/
/*    Author: Scott Bevin                                               */
/************************************************************************/

#pragma once

#include "../../XUtilities/MathHelper.h"
#include "OgreRenderer.h"
#include "../../XFrameworkTypedefsAndDefines.h"
namespace XF
{
	class OrbitalCamera
	{
	private:
		Ogre::SceneNode *mTargetNode;
		Ogre::SceneNode *mCameraNode;
		Ogre::Camera *mCamera;

		std::string mName;

		XF::OgreRenderer *mRenderer;

		float mTightness;

		float mDistance, mDesiredDistance, mMaxDist, mMinDist;
		float mYaw, mDesiredYaw;
		float mPitch, mDesiredPitch;
		float mRoll, mDesiredRoll;

		XF::Vector3 mDesiredTargetPos;

		void UpdatePosition( double dT );
		void UpdateDistance( double dT );
		void UpdateOrientation( double dT );

	public:
		OrbitalCamera(XF::OgreRenderer *renderer);
		~OrbitalCamera();

		XF::Vector3 GetPosition(){return mCamera->getRealPosition();} //chris
		XF::Vector3 GetLookAtDirection();	//chris
		
		float Tightness() const { return mTightness; }
		void Tightness(float val) { mTightness = val; }

		float Distance() const { return mDistance; }
		void Distance(float val, bool instantUpdate = false);
		void AddToDistance(float val, bool instantUpdate = false){Distance(mDesiredDistance + val, instantUpdate);}

		float Yaw() const { return mYaw; }
		void Yaw(float val, bool instantUpdate = false);
		void AddToYaw(float val, bool instantUpdate = false){Yaw(mDesiredYaw + val, instantUpdate);}

		float Pitch() const { return mPitch; }
		void Pitch(float val, bool instantUpdate = false);
		void AddToPitch(float val, bool instantUpdate = false){Pitch(mDesiredPitch + val, instantUpdate);}

		float Roll() const { return mRoll; }
		void Roll(float val, bool instantUpdate = false);
		void AddToRoll(float val, bool instantUpdate = false){Roll(mDesiredRoll + val, instantUpdate);}

		XF::Vector3 FocalPoint(){return mTargetNode->getPosition();}
		void FocalPoint(XF::Vector3 val, bool instantUpdate = false);
		void AddToFocalPoint(XF::Vector3 val, bool instantUpdate = false){FocalPoint(mDesiredTargetPos + val, instantUpdate);}
		void AddToFocalPointRelative(XF::Vector3 val, bool instantUpdate = true);//chris

		float MinDist() const { return mMinDist; }
		void MinDist(float val) { mMinDist = val; }
		float MaxDist() const { return mMaxDist; }
		void MaxDist(float val) { mMaxDist = val; }

		void Update(double dT);
	};
}
